package com.luaj.elasticsearch.service.impl;

import com.luaj.elasticsearch.mapper.ShopMapper;
import com.luaj.elasticsearch.pojo.Shop;
import com.luaj.elasticsearch.service.ShopService;
import com.luaj.elasticsearch.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 卢安杰
 * @date 2020-11-20 20:06
 */
@Service
public class ShopServiceImpl implements ShopService {
    @Autowired
    private ShopMapper shopMapper;
    @Override
    public int countAllShop() {
        return shopMapper.selectCount(null);
    }

    @Override
    public void create(Shop shopModel) {
        shopMapper.insertSelective(shopModel);
    }

    @Override
    public List<Shop> selectAll() {
        return shopMapper.selectAll();
    }

    @Override
    public List<Shop> recommend(BigDecimal longitude, BigDecimal latitude) {
        List<Shop> shops = shopMapper.selectAll();
        shops.stream().forEach(e->{
            double disntance = Math.ceil(1 + 1000 * (2 * 6378.137 * Math.asin(Math.sqrt(Math.pow(Math.sin(new BigDecimal(Math.PI).multiply(longitude.subtract(e.getLatitude())).divide(new BigDecimal(360)).doubleValue()), 2) + Math.cos(new BigDecimal(Math.PI).multiply(latitude).divide(new BigDecimal(180)).doubleValue())
                    * Math.cos(e.getLatitude().multiply(new BigDecimal(Math.PI)).divide(new BigDecimal(180)).doubleValue()) * Math.pow(Math.sin(new BigDecimal(Math.PI).multiply(longitude.subtract(e.getLongitude())).divide(new BigDecimal(360)).doubleValue()), 2)))));
            e.setDinstance(disntance);
        });
        return shops.stream().sorted(new Comparator<Shop>() {
            @Override
            public int compare(Shop o1, Shop o2) {
                double v = (0.95 * 1 / Math.log10(o1.getDinstance()) + 0.05 * o1.getRemarkScore().doubleValue() / 5) - (0.95 * 1 / Math.log10(o2.getDinstance()) + 0.05 * o2.getRemarkScore().doubleValue() / 5);
                if(v==0) return 0;
                return v>0?-1:1;
            }
        }).collect(Collectors.toList());
    }

    @Override
    public List<Shop> search(BigDecimal longitude, BigDecimal latitude, String keyword, Integer orderby, Integer categoryId, String tags) {
        WeekendSqls<Shop> sqls=WeekendSqls.<Shop>custom();
        if(StringUtils.isNotBlank(keyword)){
            sqls.andLike(Shop::getName,'%'+keyword+'%');
        }
        if(categoryId!=null){
            sqls.andEqualTo(Shop::getCategoryId,categoryId);
        }
        if(StringUtils.isNotBlank(tags)){
            sqls.andEqualTo(Shop::getTags,tags);
        }
        Example.Builder builder = Example.builder(Shop.class).where(sqls);
        if(orderby==1){
            builder.orderByAsc("pricePerMan").orderByAsc("id");
        }
        //Example.builder(Shop.class).where(sqls)
        List<Shop> shops = shopMapper.selectByExample(builder.build());
        shops.stream().forEach(e->{
            double disntance = Math.ceil(1 + 1000 * (2 * 6378.137 * Math.asin(Math.sqrt(Math.pow(Math.sin(new BigDecimal(Math.PI).multiply(longitude.subtract(e.getLatitude())).divide(new BigDecimal(360)).doubleValue()), 2) + Math.cos(new BigDecimal(Math.PI).multiply(latitude).divide(new BigDecimal(180)).doubleValue())
                    * Math.cos(e.getLatitude().multiply(new BigDecimal(Math.PI)).divide(new BigDecimal(180)).doubleValue()) * Math.pow(Math.sin(new BigDecimal(Math.PI).multiply(longitude.subtract(e.getLongitude())).divide(new BigDecimal(360)).doubleValue()), 2)))));
            e.setDinstance(disntance);
        });
        if(orderby==null){
            return shops.stream().sorted(new Comparator<Shop>() {
                @Override
                public int compare(Shop o1, Shop o2) {
                    double v = (0.95 * 1 / Math.log10(o1.getDinstance()) + 0.05 * o1.getRemarkScore().doubleValue() / 5) - (0.95 * 1 / Math.log10(o2.getDinstance()) + 0.05 * o2.getRemarkScore().doubleValue() / 5);
                    if(v==0) return 0;
                    return v>0?-1:1;
                }
            }).collect(Collectors.toList());
        }
        return shops;

    }

    @Override
    public List<Map<String, Object>> searchGroupByTags(String keyword, Integer categoryId, String tags) {
        WeekendSqls<Shop> sqls=WeekendSqls.<Shop>custom();
        if(StringUtils.isNotBlank(keyword)){
            sqls.andLike(Shop::getName,'%'+keyword+'%');
        }
        if(categoryId!=null){
            sqls.andEqualTo(Shop::getCategoryId,categoryId);
        }
        if(StringUtils.isNotBlank(tags)){
            sqls.andEqualTo(Shop::getTags,tags);
        }


        //Example.builder(Shop.class).where(sqls)
        List<Shop> shops = shopMapper.selectByExample(Example.builder(Shop.class).where(sqls).select("tags").build());
        Map<String, Long> list = shops.stream()
                .map(e -> e.getTags())
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        return  list.entrySet().stream().map(e->{
            Map<String, Object> map = new HashMap<>();
            map.put("tags",e.getKey());
            map.put("num",e.getValue());
            return map;
        }).collect(Collectors.toList());

    }
}
